﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml;

namespace MangaManagerLib
{
    
    public class MangaManager
    {
        const string MANGA_CONGIF_FILE = "manga.config";
        public static MangaManager GetInstance()
        {
            if (instance == null)
                instance = new MangaManager();
            return instance;
        }
        
        private static MangaManager instance;
        private Dictionary<string, IMangaOperation> mangaPluginDict;
        private MangaManager()
        {
            Logger.GetInstance().Info("Constuctor Manga Manager");
            mangaPluginDict = new Dictionary<string, IMangaOperation>();
        }

        private IMangaOperation GetMangaOperationByKey(string key)
        {
            IMangaOperation resultValue = null;
            if (mangaPluginDict.ContainsKey(key) )
            {
                resultValue = mangaPluginDict[key];
            }
            else 
            {
                resultValue = LoadMangaOperationFromDll(key);
                if(resultValue != null)
                    mangaPluginDict.Add(key, resultValue);
            }
            return resultValue;
        }

        public IList<string> GetDataForChapter(string key, string url)
        {
            IMangaOperation mangaOperation = GetMangaOperationByKey(key);
            if (mangaOperation != null)
            {
                return mangaOperation.GetDataForChapter(url);
            }
            return null;
        }

        private IMangaOperation LoadMangaOperationFromDll(string key)
        {
            //read plugin path from manga config file

            //string pluginPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string pluginPath = System.IO.Path.GetDirectoryName(
      System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", string.Empty)  ;
            string mangaConfigFile = Path.Combine(pluginPath, MANGA_CONGIF_FILE);
            XmlDocument xmlDocument = new XmlDocument();
            bool isKeyValid = false;
            try
            {
                xmlDocument.Load(mangaConfigFile);
                XmlNodeList nodeList = xmlDocument.DocumentElement.GetElementsByTagName("site");
                foreach(XmlNode node in nodeList)
                {
                    if (node.Attributes["key"].Value.Equals(key))
                    {
                        pluginPath = Path.Combine(pluginPath, node.Attributes["value"].Value);
                        isKeyValid = true;
                        break;
                    }
                }

            }
            catch(Exception ex)
            {
                Logger.GetInstance().LogException(ex);
                return null;
            }
            if (!isKeyValid)
            {
                Logger.GetInstance().Debug("Key is not valid");
                return null;
            }
            //load managa dll from path
            Assembly assembly = null;
            try
            {
                assembly = Assembly.LoadFile(pluginPath);
            }
            catch (System.Exception ex)
            {
                return null;
            }
            List<Type> availableTypes = new List<Type>();
            availableTypes.AddRange(assembly.GetTypes());
            List<Type> listofTypeInDll = availableTypes.FindAll(delegate(Type t)
            {
                List<Type> interfaceTypes = new List<Type>(t.GetInterfaces());
                object[] arr = t.GetCustomAttributes(typeof(MangaPluginAttribute), true);
                return !(arr == null || arr.Length == 0) && interfaceTypes.Contains(typeof(IMangaOperation));
            });
            List<IMangaOperation> temps = null;
            try
            {
                temps = listofTypeInDll.ConvertAll<IMangaOperation>(delegate(Type t) { return Activator.CreateInstance(t) as IMangaOperation; });
            }
            catch (System.Exception ex)
            {
                Logger.GetInstance().LogException(ex);
                return null;
            }
            if (temps != null && temps.Count > 0)
            {
                return temps[0];
            }
            return null;
        }

        public MangaStoryDetail GetMangaStoryDetail(string key, string url)
        {
            IMangaOperation mangaOperation = GetMangaOperationByKey(key);
            if (mangaOperation != null)
            {
                return mangaOperation.GetMangaStoryDetail(url);
            }
            return null;
        }

        public MangaCollection GetMangaCollection(string key, string url, int page)
        {
            IMangaOperation mangaOperation = GetMangaOperationByKey(key);
            if (mangaOperation != null)
            {
                return mangaOperation.GetMangaCollection(url, page);
            }
            return null;
            
        }
        public IList<MangaStory> GetNewestManga(string key,int numberToGet)
        {
            IMangaOperation mangaOperation = GetMangaOperationByKey(key);
            if (mangaOperation != null)
            {
                return mangaOperation.GetNewestManga(numberToGet);
            }
            return null;
        }
        public IList<MangaStory> GetPopularManga(string key, int numberToGet)
        {
            IMangaOperation mangaOperation = GetMangaOperationByKey(key);
            if (mangaOperation != null)
            {
                return mangaOperation.GetPopularManga(numberToGet);
            }
            return null;
        }
        public IList<MangaStory> SearchMangaByTitle(string key, string keySearch)
        {
            IMangaOperation mangaOperation = GetMangaOperationByKey(key);
            if (mangaOperation != null)
            {
                return mangaOperation.SearchMangaByTitle(keySearch);
            }
            return null;
        }
    }
}
